/* 
 * File:   chat.c
 * Author: ntthinh
 *
 * Created on December 15, 2009, 11:49 PM
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include<string.h>
#include<stddef.h>
#include <pthread.h>
#include <fcntl.h>

#define SIZE 1024
//socket pour deux utilisateur 
struct sockaddr_in local_addr, remote_addr;
int sockfd;//sock descriptor

//fonction pour envoyer le message
void *send_message(void *argv)
{
	int remotelen = sizeof(remote_addr);	
	char  msg[SIZE];
	while(1)
	{
		scanf("%s",msg);
		if (sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *)&remote_addr, remotelen)!=strlen(msg))
			printf("client: sendto error \n");
 		msg[0]='\0';
	}
}
//fonction pour recevoir le message
void *recv_message(void *argv)
{
	int remotelen = sizeof(remote_addr);	
	char msg[SIZE];
	//declarer un structure fd_set  	
	fd_set fdset;
	// pour tous les descripteurs de fichiers, fixer les bits de fdset à zéro
	FD_ZERO(&fdset);	
	//Définit les bits du descripteur de fichier sockfd est fdset.
	FD_SET(sockfd,&fdset);
	while(1)
	{
		//Indiquer le "File descritor " est prêt à marcher		
		select(sockfd + 1, &fdset,NULL,NULL,NULL);
		if (FD_ISSET(sockfd, &fdset))
		{
			if (recvfrom(sockfd, msg, SIZE, 0, (struct sockaddr *)&remote_addr, (socklen_t*)&remotelen)<0)
			printf("\n recv error");
		}
		printf("%s\n",msg);
		msg[0]='\0';
	}
}

//fonction principale
int main(int argc, char *argv[]) 
{
	pthread_t thread_id[2];//deux thread pour envoyer et recevoir le message
	int local_port, remote_port;
	char* remote_host;
	
	if (argc != 4)
	{
		perror("Invalid argument\n");
		perror("usage: ./chat.o REMOTE_ADDR LOCAL_PORT REMOTE_PORT\n");
		exit(-1);
	}
	else
	{
		remote_host = argv[1];//le premier argument, c'est l'adresse de autre utilisateur
		remote_port = atoi(argv[2]);
		local_port = atoi(argv[3]);
	}
	
	 if ( (sockfd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
           printf("\n server: can't open datagram socket");  /*we assume  
                              this performs perror() and exit(-1)*/
      
  /* Bind "local address" pour recevoir le message */
	bzero(&local_addr, sizeof(local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = INADDR_ANY;
	local_addr.sin_port = htons(local_port);

	if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(local_addr))<0)
           printf("server: can't bind local address");
	
  /* Bind "remote address" pour envoyer des messages */
	bzero(&remote_addr, sizeof(remote_addr));
	remote_addr.sin_family = AF_INET;
	remote_addr.sin_addr.s_addr = inet_addr(remote_host);//htonl(INADDR_ANY);
	remote_addr.sin_port = htons(remote_port);
	
	/* utiliser deux thread pour envoyer et recevoir les messages */
	int ret1 = pthread_create(&thread_id[0], NULL, send_message, NULL);
	int ret2= pthread_create(&thread_id[1], NULL, recv_message, NULL);
	/*attendre pour la termination de thread*/
	pthread_join(thread_id[0], NULL);
	pthread_join(thread_id[1], NULL);
}


